import { VNode } from "vue";

export type BaseComponentType =  "Cell" | "Tab" | "Button" | "ActionBar" | "Input" | "Select" | "Date" | "Radio" | "Html" | "Table" | "Upload" | "Slot"
export type ContainerComponentType = "Form" | "Card" | "Tabs" | "Collapse" | "Row" | "Modal"
export type ComponentType = "Root" | BaseComponentType | ContainerComponentType


export type LowCodeType = {
    isDesigner?: boolean;
    root?:ComponentImp;
    model?: any,
    fieldPool?:any[],
    eventCollection?: Array<EventType>;
    dataSource?: Array<DataSourceType>;
    globalConfig?: GlobalConfig
}

export interface LowCodeImp extends LowCodeType {
    isDesigner?: boolean;
    disabled?: boolean;
    dataCenter: any;
    root?: ComponentImp;
    [x: string]: any;
    currentKey: string;
    model: any;
    fieldPool?:any[]
    eventCollection: Array<EventType>;
    dataSource: Array<DataSourceType>;
    modelController: ModelImp,//modelController 数据控制类
    formController: FormImp,
    eventCenterController: EventCenterImp,//eventCenterController 事件控制器
    dataSourceController: DataSourceImp,//dataSourceController 数据源控制器
    updateMetaRefresh: () => void;
    buildDomTree: () => void;
    registrationControl: () => void;
    setcurrentKey: (key: string) => void,
}

export interface ComponentImp {
    key: string;
    component: ComponentType;
    name: string;
    field: string;
    required?: boolean,
    selector: string,
    group: string;
    describe: string;
    nestedChain: string;
    componentProps: any;
    render?:VNode,
    style?: any;
    items?: Array<ComponentImp | CellImp | TabImp>;
    updateMetaRefresh?: () => void;
    getLowCodeInstance?: () => LowCodeImp;
    addItem: (
        com: ComponentImp | CellImp | TabImp
    ) => ComponentImp | CellImp | TabImp;
    copyItem:  (com: ComponentImp | CellImp | TabImp, newkey: boolean) => ComponentImp | CellImp | TabImp;
    removeItem: (key: string) => void;
    modelBing?: () => void
}

export type ComponentImpWithoutMethods = Omit<ComponentImp, 'addItem' | 'copyItem' | 'removeItem'>;

export interface CellImp<T = any> {
    key: string;
    component: string;
    [x: string]: any;
    componentProps?: any;
    items?: Array<T>;
}

export interface TabImp<T = any> {
    key: string;
    name?:  string;
    tabIndex:  number | string;
    [x: string]: any;
    component: string;
    componentProps?: any;
    items?: Array<T>;
}

export interface ModelImp {
    modelTree: any;
    fieldPoolMap: { [key: string]: any };
    modelKeyList: { [key: string]: string }[];
    buildModelTree: () => void;
    buildModelKeyList: () => void;
    saveModel: (key: string, field: any) => void;
    selectModel: (key: string) => any;
    removeModel: (key: string) => void
}

export interface FormImp {
    formRefs: Map<string, any>
    [x: string]: any;
}

export interface TableImp {
     tableRefs: Map<string, any>
    [x: string]: any;
}


export interface EventCenterImp<T = any> {
    init: () => void;
    addEvent: (type: string, describe: string, options: any, event: string) => void;
    editorEvent: (type: string, code: string, options: any, describe: string, event: string) => void
    removeEvent: (code: string) => void
    on: (key: string, listener: Function) => EventCenterImp;
    fire: (key: string, ...params: any[]) => Promise<T> | boolean;
    off: (key: string, listener: string) => void;
}

export interface EventType {
    code: string;
    type: string;
    options?: any;
    describe: string,
    func: string,
}


export interface DataSourceType {
    key: string;
    name: string;
    url: string;
    method: string;
    auto: boolean;
}
export interface DataSourceImp {
    [x: string]: any;
    currentDataSource: DataSourceType | null;
    init: () => void;
    addDataSource: () => DataSourceType;
    copyDataSource: (key: string) => void;
    removeDataSource: (key: string) => boolean;
    updateDataSource: (dataSource: DataSourceType) => boolean
}

export interface GlobalConfig {
    labelPosition: "horizontal" | "vertical",
    size: "default" | "large" | "small"
}


export interface SelectorImp {
    find: (name: string) => SelectorImp | boolean;
    set: (key: string, value: any) => SelectorImp
    get: (key?: string) => unknown
}






